package ext.acae2.baseline.helper;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Vector;

import org.apache.log4j.Logger;

import wt.enterprise.RevisionControlled;
import wt.fc.Persistable;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.fc.ReferenceFactory;
import wt.fc.WTObject;
import wt.lifecycle.LifeCycleHelper;
import wt.lifecycle.LifeCycleManaged;
import wt.lifecycle.State;
import wt.locks.LockHelper;
import wt.log4j.LogR;
import wt.org.WTGroup;
import wt.org.WTPrincipal;
import wt.org.WTPrincipalReference;
import wt.org.WTUser;
import wt.pds.StatementSpec;
import wt.project.Role;
import wt.query.ClassAttribute;
import wt.query.OrderBy;
import wt.query.OrderByExpression;
import wt.query.QueryException;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.session.SessionServerHelper;
import wt.team.Team;
import wt.util.WTException;
import wt.util.WTProperties;
import wt.util.WTPropertyVetoException;
import wt.util.WTRuntimeException;
import wt.vc.baseline.ManagedBaseline;
import wt.workflow.engine.WfActivity;
import wt.workflow.engine.WfBlock;
import wt.workflow.engine.WfContainer;
import wt.workflow.engine.WfProcess;
import ext.acae2.baseline.BaselineConstants;
import ext.acae2.mail.EmailUtility;
import ext.acae2.mail.util.MailUtility;
import ext.acae2.workflow.TaskConfigrationHelper;

/**
 * @desription baseline helper
 * @author cnie
 * @date 2013-3-5 上午12:59:49
 */
public class BaselineHelper {

	static final int QUERY_LIMIT = 500;
	static final int INDEX = 0;

	private static final Logger LOGGER = LogR.getLogger(BaselineHelper.class
			.getName());

	private static String rmiHost;
	private static String protocol;
	private static String webappName;

	static {
		try {
			WTProperties props = WTProperties.getLocalProperties();
			rmiHost = props.getProperty("java.rmi.server.hostname");
			protocol = props.getProperty("wt.webserver.protocol");
			webappName = props.getProperty("wt.webapp.name");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	/**
	 * 
	 * @description get ByNumber
	 * @author cnie
	 * @date 2013-3-28 上午11:48:00
	 * @version 1.0
	 * @param number
	 * @return
	 */
	public static ManagedBaseline getBaseLineByNumber(String number){
		Class<ManagedBaseline> cls = ManagedBaseline.class;
		QuerySpec qs;
		try {
			qs = new QuerySpec(cls);
			qs.setAdvancedQueryEnabled(true);
			//qs.setQueryLimit(QUERY_LIMIT);
			qs.appendWhere(new SearchCondition(cls, ManagedBaseline.NUMBER,
					SearchCondition.EQUAL, number, false),
					new int[] { INDEX });
			qs.appendAnd();
			qs.appendWhere(new SearchCondition(cls,
					ManagedBaseline.LIFE_CYCLE_STATE, SearchCondition.NOT_EQUAL,
					BaselineConstants.LIFECYCLE_RELEASE_STATE, false),
					new int[] { INDEX });
			QueryResult qr = PersistenceHelper.manager.find((StatementSpec) qs);
			if (qr.hasMoreElements()) {
				ManagedBaseline baseline = (ManagedBaseline) qr.nextElement();
				return baseline;
			}
		} catch (WTException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
	}

	/**
	 * @description search like number
	 * @author cnie
	 * @date 2013-3-2 下午12:26:40
	 * @version 1.0
	 * @param baselineNum
	 * @return
	 */
	public static String searchBaselineLikeNumber(String baselineNum) {
		String baselineNumber = null;
		Class<ManagedBaseline> cls = ManagedBaseline.class;
		try {
			ClassAttribute clsAttr = new ClassAttribute(cls,
					ManagedBaseline.NUMBER);
			QuerySpec qs = new QuerySpec(cls);
			// int clsIndex = qs.appendClassList(cls, false);
			qs.setAdvancedQueryEnabled(true);
			qs.setQueryLimit(QUERY_LIMIT);
			// qs.appendSelect((ColumnExpression)clsAttr, new int[]{0},true);
			qs.appendWhere(new SearchCondition(cls, ManagedBaseline.NUMBER,
					SearchCondition.LIKE, baselineNum + "%", false),
					new int[] { INDEX });
			qs.appendAnd();
			qs.appendWhere(new SearchCondition(cls,
					ManagedBaseline.LIFE_CYCLE_STATE, SearchCondition.EQUAL,
					BaselineConstants.LIFECYCLE_RELEASE_STATE, false),
					new int[] { INDEX });
			/** true Desc */
			OrderBy order = new OrderBy((OrderByExpression) clsAttr, true);
			qs.appendOrderBy(order, new int[] { INDEX });
			QueryResult qr = PersistenceHelper.manager.find((StatementSpec) qs);
			if (qr.hasMoreElements()) {
				ManagedBaseline baseline = (ManagedBaseline) qr.nextElement();
				baselineNumber = baseline.getNumber();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return baselineNumber;
	}

	/**
	 * 
	 * @description get baseline member and lock the baseline and baselineable
	 * @author cnie
	 * @date 2013-3-6 下午3:00:35
	 * @version 1.0
	 * @param mbl
	 * @return
	 */
	public static void sendEmail(ManagedBaseline mbl) {
		Vector touserEmails = new Vector();
		List<WTPrincipal> tousers = new ArrayList<WTPrincipal>();
		String lockReason = "baseline release";
		try {
			WTPrincipalReference mdlOwner = mbl.getCreator();
			QueryResult itemQr = wt.vc.baseline.BaselineHelper.service
					.getBaselineItems(mbl);
			// touserEmails.add("rick@acae.com");
			// touserEmails.add("cnie@acae.com");
			while (itemQr.hasMoreElements()) {
				Object obj = itemQr.nextElement();
				if (obj instanceof RevisionControlled) {
					RevisionControlled rc = (RevisionControlled) obj;
					WTUser itemOwner = (WTUser) rc.getCreator().getPrincipal();
					tousers.add(itemOwner);
					String itemEmail = itemOwner.getEMail();
					if (!touserEmails.contains(itemEmail)) {
						LOGGER.debug("=========itemEmail===========>"
								+ itemEmail);
						touserEmails.add(itemEmail);
					}
				}
			}

			// if(!LockHelper.isLocked(mbl)){
			// mbl = (ManagedBaseline) LockHelper.assignLock(mbl, mdlOwner,
			// lockReason);
			// }

			// mbl = (ManagedBaseline) PersistenceHelper.manager.save(mbl);

			if (!LockHelper.isLocked(mbl)) {
				mbl = (ManagedBaseline) LockHelper.lock(mbl);
			}

			String subject = "基线被锁定，请查看包含对象";
			ReferenceFactory rf = new ReferenceFactory();
			String mdlOid = rf.getReferenceString(mbl);
			String url = protocol + "://" + rmiHost + "/" + webappName
					+ "/app/#ptc1/tcomp/infoPage?u8=1&oid=" + mdlOid; // baseline
																		// infopage
			String infopage = "<a href=\"" + url + "\" target=\"_blank\">"
					+ mbl.getNumber() + "</a>";
			String content = "编号：" + infopage + "  名称：" + mbl.getName()
					+ "  基线被锁定，相关的构型文件在该基线中,请查阅。";
			// DataHandler dh = new DataHandler(content,
			// "text/html;charset=UTF-8");
//			MailUtility.sendMail(touserEmails, subject, content);
			Map<String, Object> map = new HashMap<String, Object>();
			map.put(EmailUtility.EMAIL_TITLE, subject);
			map.put(EmailUtility.EMAIL_CONTENT, content);
			EmailUtility.sendEmail(map, tousers, null);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @description check gouxingwenjian state is released
	 * @author cnie
	 * @date 2013-3-18 下午3:16:02
	 * @version 1.0
	 * @param mbl
	 * @return
	 * @throws WTException
	 */
	public static void checkBaselineablesState(WTObject wtObj)
			throws WTException {
		if (wtObj instanceof ManagedBaseline) {
			ManagedBaseline mbl = (ManagedBaseline) wtObj;
			QueryResult itemQr = wt.vc.baseline.BaselineHelper.service
					.getBaselineItems(mbl);

			if (itemQr == null || itemQr.size() == 0) {
				throw new WTException("基线中不包含构型文件");
			} else {
				StringBuffer messagesb = new StringBuffer();
				while (itemQr.hasMoreElements()) {
					Object obj = itemQr.nextElement();
					if (obj instanceof LifeCycleManaged) {
						LifeCycleManaged lfm = (LifeCycleManaged) obj;
						String lfmState = lfm.getState().toString();
						if (!"RELEASED".equals(lfmState)) {
							RevisionControlled rc = (RevisionControlled) obj;
							String name = rc.getName();
							messagesb.append(name);
							messagesb.append(",");
						}
					}
				}
				if (messagesb != null && !"".equals(messagesb.toString())) {
					String message = "对象"
							+ messagesb.toString().substring(0,
									messagesb.toString().length() - 1)
							+ " 的状态不符合添加到基线的条件,必须为‘已发布’状态";
					throw new WTException(message);
				}
			}
		}

	}

	/**
	 * 
	 * @description check Role Principal
	 * @author cnie
	 * @date 2013-3-18 下午7:04:38
	 * @version 1.0
	 * @param process
	 * @throws WTException
	 */
	public static void checkRoleParticipant(Object obj) throws WTException {
		WfProcess process = null;
		if (obj instanceof WfProcess) {
			process = (WfProcess) obj;
		} else if (obj instanceof WfActivity) {
			WfActivity activity = (WfActivity) obj;
			WfContainer wfcont = (WfContainer) activity.getParentProcessRef()
					.getObject();
			if (wfcont instanceof WfBlock) {
				WfBlock wb = (WfBlock) wfcont;
				wfcont = wb.getParentProcess();
			}
			process = (WfProcess) wfcont;
		}

		Team processTeam = (Team) process.getTeamId().getObject();
		@SuppressWarnings("unchecked")
		Map<Role, List<WTPrincipalReference>> rolePrincipalMap = processTeam
				.getRolePrincipalMap();
		Map<Role, List<WTUser>> roleUserMap = new HashMap<Role, List<WTUser>>();
		List<WTUser> users = null;
		for (java.util.Iterator<Role> roles = rolePrincipalMap.keySet()
				.iterator(); roles.hasNext();) {
			Role role = roles.next();
			List<WTPrincipalReference> wtrprincipalrefs = rolePrincipalMap
					.get(role);
			if (wtrprincipalrefs == null || wtrprincipalrefs.size() == 0) {
				throw new WTException("流程角色：" + role.getDisplay(Locale.CHINA) + "没有设置参与者");
			} else {

				for (WTPrincipalReference wtprincipalref : wtrprincipalrefs) {
					users = new ArrayList<WTUser>();
					Persistable persistable = wtprincipalref.getObject();
					if (persistable instanceof WTUser) {
						WTUser user = (WTUser) persistable;
						if (!users.contains(user)) {
							users.add(user);
						}
					} else if (persistable instanceof WTGroup) {
						WTGroup group = (WTGroup) persistable;
						List<WTUser> groupUsers = getGroupMembersOfUser(group);
						for (WTUser groupUser : groupUsers) {
							if (!users.contains(groupUser)) {
								users.add(groupUser);
							}
						}
					}
					if (users == null || users.size() == 0) {
						throw new WTException("流程角色：" + role.getDisplay(Locale.CHINA)
								+ "没有设置参与者");
					}
					if (roleUserMap != null && roleUserMap.size() != 0) {
						for (WTUser user : users) {
							for (java.util.Iterator<Role> addroles = roleUserMap
									.keySet().iterator(); addroles.hasNext();) {
								Role addrole = addroles.next();
								if (!addrole.equals(role)) {
									List<WTUser> addusers = roleUserMap
											.get(addrole);
									if (addusers.contains(user)) {
										throw new WTException("流程角色："
												+ role.getDisplay(Locale.CHINA) + "与"
												+ addrole.getDisplay(Locale.CHINA)
												+ "存在相同的参与者："
												+ user.getFullName());
									}
								}
							}
						}
					}

				}
				roleUserMap.put(role, users);
			}
		}
	}

	private static List<WTUser> getGroupMembersOfUser(WTGroup group)
			throws WTException {
		List<WTUser> users = new ArrayList<WTUser>();
		Enumeration member = group.members();

		while (member.hasMoreElements()) {
			WTPrincipal principal = (WTPrincipal) member.nextElement();
			if (principal instanceof WTUser) {
				users.add((WTUser) principal);
			} else if (principal instanceof WTGroup) {
				List<WTUser> ausers = getGroupMembersOfUser((WTGroup) principal);
				for (int i = 0; i < ausers.size(); i++) {
					users.add(ausers.get(i));
				}
			}
		}

		return users;
	}

	/**
	 * 
	 * @description set baseline lifecycle state
	 * @author cnie
	 * @date 2013-3-27 下午4:21:25
	 * @version 1.0
	 * @param wioid
	 * @throws WTException
	 * @throws WTRuntimeException
	 */
	public static void setBaselineState(String wioid)
			throws WTRuntimeException, WTException {
		boolean enforce = SessionServerHelper.manager.setAccessEnforced(false);
		Object obj = TaskConfigrationHelper.getActivityVariableByVarName(wioid,
				"primaryBusinessObject");
		if (obj instanceof ManagedBaseline) {
			ManagedBaseline baseline = (ManagedBaseline) obj;
			if (baseline instanceof LifeCycleManaged) {
				LifeCycleHelper.service.setLifeCycleState(baseline, State
						.toState(BaselineConstants.LIFECYCLE_PRERELEASE_STATE));
			}
		}
		 SessionServerHelper.manager.setAccessEnforced(enforce);

	}

	public static void main(String[] args) throws WTException,
			WTPropertyVetoException {
		// ManagedBaseline
		// mbl=(ManagedBaseline)CSCUtil.getObjectByOid("OR:wt.vc.baseline.ManagedBaseline:243916");
		// if(!LockHelper.isLocked(mbl)){
		// mbl = (ManagedBaseline) LockHelper.a
		// }
	}

}
